#pragma once

#include "uicontrol.h"
#include "imagebutton.h"
#include "action.h"
#include "undomanager.h"

class Tool : public UIControl
{
protected:
	/** a single button that controls this tool */
	Button * m_button;
	/** the context that this tool works in */
	void * m_context;
	/** the action executed when this tool is activated */
	Action * m_activateAction;
	/** the action executed when this tool is de-activated */
	Action * m_deactivateAction;
	/** called with this tool as a parameter when the tool is activated or deactivated */
	ButtonCallbackFunction m_notified;
	/** a fast reference to what is keeping track of undo events */
	UndoManager * m_undo;
public:
	bool isOn(){return m_button->isOn();}
	void * getContext(){return m_context;}
	Button * getButton(){return m_button;}
	UndoManager * getUndoManager(){return m_undo;}
	Tool(void * a_context);
	void release(){delete m_button;m_button=0;}
	~Tool(){release();}
	static const char * NAME;
	virtual const char * getName() = 0;
	void setActivateAction(Action * a_activateAction){m_activateAction=a_activateAction;}
	void setDeactivateAction(Action * a_deactivateAction){m_deactivateAction=a_deactivateAction;}
	void setDirty(SDL_Surface * a_surface)
	{
		((Panel*)getContext())->setDirty(a_surface);
	}
	virtual void activate()
	{
		if(m_activateAction)	m_activateAction->execute();
		m_button->setOn(true);
		setDirty(0);
	}
	virtual void deactivate()
	{
		if(m_deactivateAction)	m_deactivateAction->execute();
		m_button->setOn(false);
		setDirty(0);
	}
protected:
	static void toolButtonPressed(void * a_tool)
	{
		Tool* t = (Tool*)a_tool;
		if(t->m_notified)	t->m_notified(t);
		Button * b = t->getButton();
		// if the button is on, or if it will always have the same state
		if(!b->isToggleable() || b->isOn())
			t->activate();
		else
			t->deactivate();
	}
public:
	virtual void setContext(void * a_context, ButtonCallbackFunction a_notified)
	{
		m_context = a_context;
		m_notified = a_notified;
		m_button->setAction(toolButtonPressed, this);
	}
	virtual void draw(SDL_Surface * a_surface){}
	virtual bool update(const int & a_ms){return false;}
};